"""
登录日志中间件
"""
from django.utils import timezone
from django.contrib.auth.signals import user_logged_in, user_logged_out
from django.dispatch import receiver
from .models import LoginLog


def get_client_ip(request):
    """获取客户端IP地址"""
    x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
    if x_forwarded_for:
        ip = x_forwarded_for.split(',')[0]
    else:
        ip = request.META.get('REMOTE_ADDR')
    return ip


def get_user_agent(request):
    """获取用户代理"""
    return request.META.get('HTTP_USER_AGENT', '')


@receiver(user_logged_in)
def log_user_login(sender, request, user, **kwargs):
    """记录用户登录"""
    try:
        # 获取客户端信息
        ip_address = get_client_ip(request)
        user_agent = get_user_agent(request)
        session_key = request.session.session_key
        
        # 创建登录日志
        login_log = LoginLog.objects.create(
            user=user,
            ip_address=ip_address,
            user_agent=user_agent,
            session_key=session_key,
            login_time=timezone.now(),
            is_success=True
        )
        
        # 将登录日志ID存储到session中，用于后续的退出记录
        request.session['login_log_id'] = login_log.id
        
        # 更新用户最后登录IP
        user.last_login_ip = ip_address
        user.save(update_fields=['last_login_ip'])
        
    except Exception as e:
        # 记录日志失败不应该影响正常登录流程
        print(f"记录登录日志失败: {str(e)}")


@receiver(user_logged_out)
def log_user_logout(sender, request, user, **kwargs):
    """记录用户退出"""
    try:
        # 从session中获取登录日志ID
        login_log_id = request.session.get('login_log_id')
        
        if login_log_id:
            try:
                login_log = LoginLog.objects.get(id=login_log_id, user=user)
                login_log.logout_time = timezone.now()
                login_log.save(update_fields=['logout_time'])
            except LoginLog.DoesNotExist:
                pass
        else:
            # 如果没有找到对应的登录记录，尝试找到最近的未退出记录
            recent_login = LoginLog.objects.filter(
                user=user,
                logout_time__isnull=True
            ).order_by('-login_time').first()
            
            if recent_login:
                recent_login.logout_time = timezone.now()
                recent_login.save(update_fields=['logout_time'])
                
    except Exception as e:
        # 记录日志失败不应该影响正常退出流程
        print(f"记录退出日志失败: {str(e)}")


class LoginLogMiddleware:
    """登录日志中间件"""
    
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        return response

    def process_exception(self, request, exception):
        """处理异常时的日志记录"""
        # 如果是登录相关的异常，可以在这里记录失败日志
        return None


def record_failed_login(request, username, reason):
    """记录登录失败"""
    try:
        from django.contrib.auth import get_user_model
        User = get_user_model()
        
        # 尝试获取用户对象
        user = None
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            pass
        
        # 记录失败日志
        LoginLog.objects.create(
            user=user,  # 如果用户不存在则为None
            ip_address=get_client_ip(request),
            user_agent=get_user_agent(request),
            login_time=timezone.now(),
            is_success=False,
            failure_reason=reason
        )
    except Exception as e:
        print(f"记录登录失败日志失败: {str(e)}")


def cleanup_old_sessions():
    """清理过期的在线状态"""
    from django.contrib.sessions.models import Session
    from datetime import timedelta
    
    try:
        # 获取所有有效的session key
        valid_sessions = set(Session.objects.filter(
            expire_date__gt=timezone.now()
        ).values_list('session_key', flat=True))
        
        # 找到session已过期但仍显示在线的登录记录
        expired_logins = LoginLog.objects.filter(
            logout_time__isnull=True,
            session_key__isnull=False
        ).exclude(session_key__in=valid_sessions)
        
        # 将这些记录标记为已退出
        for login in expired_logins:
            # 估算退出时间为session过期时间
            try:
                session = Session.objects.get(session_key=login.session_key)
                login.logout_time = session.expire_date
            except Session.DoesNotExist:
                # 如果session不存在，设置为24小时后自动退出
                login.logout_time = login.login_time + timedelta(hours=24)
            
            login.save(update_fields=['logout_time'])
            
    except Exception as e:
        print(f"清理过期会话失败: {str(e)}")
